﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSE.ProcessManager.Entity;
using System.Threading;

namespace PSE.ProcessManager.ResourceAccess.FileSystemProvider
{
    public class MessageResourceAccess : BaseFileAccess
    {
        private static Mutex _mtxLock = new Mutex(false, "PSE.ProcessManager.ResourceAccess.FileSystemProvider.Message.MtxLock");

        private string _filePath;
        public MessageResourceAccess(string filePath)
        {
            _filePath = filePath;
        }

        public List<MessageEntity> GetAll()
        {
            List<MessageEntity> ret = base.LoadFromXmlFile<List<MessageEntity>>(_filePath);
            if (ret == null)
                ret = new List<MessageEntity>();

            return ret;
        }

        public void Delete(int messageId)
        {
            try
            {
                _mtxLock.WaitOne();

                List<MessageEntity> messages = GetAll();
                messages.RemoveAll(m => m.Id == messageId);
                base.SaveToXmlFile(_filePath, messages);
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        public void Update(MessageEntity message)
        {
            try
            {
                _mtxLock.WaitOne();

                //recuperar todas as mensagens
                List<MessageEntity> messagesInFile = GetAll();

                int index = messagesInFile.FindIndex(m => m.Id == message.Id);
                if (index >= 0)
                {
                    messagesInFile[index] = message;
                    //salvar
                    base.SaveToXmlFile(_filePath, messagesInFile);
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        public void Update(List<MessageEntity> messages)
        {
            try
            {
                _mtxLock.WaitOne();

                //recuperar todas as mensagens
                List<MessageEntity> messagesInFile = GetAll();

                foreach (MessageEntity message in messages)
                {
                    int index = messagesInFile.FindIndex(m => m.Id == message.Id);
                    if (index >= 0)
                    {
                        messagesInFile[index] = message;
                    }
                }

                //salvar
                base.SaveToXmlFile(_filePath, messagesInFile);
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        public void Insert(MessageEntity entity)
        {
            try
            {
                _mtxLock.WaitOne();

                //recuperar todas as mensagens
                List<MessageEntity> messages = GetAll();

                //recuperar o id da mensagem
                entity.Id = GetNextMessageId(messages);

                //adicionar a lista
                messages.Add(entity);

                //salvar
                base.SaveToXmlFile(_filePath, messages);
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        public void Insert(List<MessageEntity> messages)
        {
            try
            {
                _mtxLock.WaitOne();

                //recuperar todas as mensagens
                List<MessageEntity> messagesInfFile = GetAll();

                int id = GetNextMessageId(messagesInfFile);
                foreach (MessageEntity message in messages)
                {
                    //recuperar o id da mensagem
                    message.Id = id;
                    //adicionar a lista
                    messagesInfFile.Add(message);

                    id++;
                }

                //salvar
                base.SaveToXmlFile(_filePath, messagesInfFile);
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        private int GetNextMessageId(List<MessageEntity> messagesInfFile)
        {
            int id;
            if (messagesInfFile.Count == 0)
                id = 1;
            else
            {
                messagesInfFile.Sort(new Comparison<MessageEntity>(CompareMessageById));
                id = messagesInfFile.Last<MessageEntity>().Id.GetValueOrDefault();
            }

            //os primeiros 100 ids de mensagens são reservados para mensagens de sistema
            if (id <= 100)
                id = 100;

            return id + 1;

        }

        private int CompareMessageById(MessageEntity a, MessageEntity b)
        {
            return a.Id.GetValueOrDefault().CompareTo(b.Id.GetValueOrDefault());
        }

        public void SaveToFile(List<MessageEntity> listMessages)
        {
            try
            {
                _mtxLock.WaitOne();

                if (listMessages != null)
                    listMessages.Sort(new Comparison<MessageEntity>(CompareMessageById));

                //salvar
                base.SaveToXmlFile(_filePath, listMessages);
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }
    }
}
